<?php
class AuthController extends MyController {
    // {{{ Members
    private $_authItem;
    public $defaultAction = 'admin';
    public $name = 'Auth Items';
    // }}} 
    // {{{ init
    public function init()
    {
        parent::init();
        $this->pageTitle = Yii::app()->name . ' - ' . Yii::t('site','Authorization');
    } // }}}
    // {{{ *** Actions ***
    // {{{ actionInit
    /**
     * Initializes a sample auth schema
     */
    public function actionInit()
    {
        $auth=Yii::app()->authManager;
         
        $auth->createOperation('createPost','create a post');
        $auth->createOperation('readPost',  'read a post');
        $auth->createOperation('updatePost','update a post');
        $auth->createOperation('deletePost','delete a post');
         
        $bizRule='return Yii::app()->user->id==$params["post"]->authID;';
        $task=$auth->createTask('updateOwnPost','update a post by author himself',$bizRule);
        $task->addChild('updatePost');
         
        $role=$auth->createRole('reader');
        $role->addChild('readPost');
         
        $role=$auth->createRole('author');
        $role->addChild('reader');
        $role->addChild('createPost');
        $role->addChild('updateOwnPost');
         
        $role=$auth->createRole('editor');
        $role->addChild('reader');
        $role->addChild('updatePost');
         
        $role=$auth->createRole('admin');
        $role->addChild('editor');
        $role->addChild('author');
        $role->addChild('deletePost');
         
        $auth->assign('reader','readerA');
        $auth->assign('author','authorB');
        $auth->assign('editor','editorC');
        $auth->assign('admin','adminD');
        
        $this->redirect(array('site/home'));

    } // }}} 
    // {{{ actionAdmin
    public function actionAdmin()
    {
        if(!Yii::app()->user->checkAccess('admin'))
            throw new CHttpException(500,Yii::t('site',"Sorry, you don't have enough privileges to perform this task."));

        $filter = isset( $_GET['filter'] ) ? $_GET['filter'] : 2;
        $where = "WHERE type=2";
        // Get roles
        $sql = sprintf("SELECT * FROM %s %s ORDER BY type DESC,name",Yii::app()->authManager->itemTable, $where);
        $command=Yii::app()->db->createCommand($sql);
        $authItems=$command->queryAll();

        // Get Children
        foreach( $authItems as $n=>$authItem ) {
            if($filter=='0,2' or $filter=='0,1,2') {
                $authItems[$n]['level'] = 0;
                $authItems[$n]['children'] = $this->getChildren($authItem['name']);
            }
        }
        $this->render(
            'admin',
            array(
                'roles'     => $authItems,
                'filter'    => $filter
            )
        );
    } // }}} 
    // {{{ actionCreate
    public function actionCreate()
    {
        $this->checkAccess('admin');
        $authItem = new AuthItem;
        if(isset($_GET['from_name']) and trim($_GET['from_name']!=='')) {
            $authItemSource=AuthItem::model()->findbyPk($_GET['from_name']);
            $itemParents = $this->getItemParents( $authItemSource->name );
            if(!is_null($authItemSource)) {
                $authItem->attributes = $authItemSource->attributes;
                $authItem->name = Yii::t('site','Copy_of_').$authItem->name;
                $authItem->description = $authItemSource->description;
            }
        }
        if(isset($_GET['parent']))
            $authItem->itemParents = array($_GET['parent']);
        if(isset($_POST['AuthItem']))
        {
            $auth = Yii::app()->authManager;
            $authItem = $auth->createAuthItem( 
                $_POST['AuthItem']['name'],
                $_POST['AuthItem']['type'],
                $_POST['AuthItem']['description'],
                $_POST['AuthItem']['bizrule'],
                $_POST['AuthItem']['data']
            );

            // Store parents
            if( count($_POST['parents'])>0 ) {
                foreach( $_POST['parents'] as $parent ) {
                    if( !$auth->hasItemChild($parent, $authItem->name) )
                        $auth->addItemChild($parent, $authItem->name);
                }
            }
            // Create CRUD operations?
            if(isset($_POST['AuthItem']['createCRUDOperations']) and $_POST['AuthItem']['createCRUDOperations']==1) {
                $operations = array(
                    'create' => 'Create a new _MODEL_NAME_',
                    'view' => 'View a _MODEL_NAME_',
                    'update' => 'Update a _MODEL_NAME_',
                    'delete' => 'Delete a _MODEL_NAME_'
                );
                $modelName = str_replace(' ','',ucwords($_POST['AuthItem']['modelName']));
                foreach($operations as $prefix => $description) {
                    $authItemCRUD = $auth->createOperation( 
                        $prefix.$modelName,
                        str_replace('_MODEL_NAME_',$_POST['AuthItem']['modelName'],$description)
                    );
                    $auth->addItemChild($_POST['AuthItem']['name'],$prefix.$modelName);
                }
            }
            //$this->setFlash( 'create', $authItem );
            $this->redirect(array('admin','filter'=>'0,2'));
        }
        $data = array('authItem'=>$authItem,'itemParents'=>$itemParents);
        $this->render('create',$data);
        
    } // }}} 
    // {{{ actionEdit
    public function actionEdit()
    {
        if(!Yii::app()->user->checkAccess('admin'))
            throw new CHttpException(500,Yii::t('site',"Sorry, you don't have enough privileges to perform this task."));

        $authItem=$this->loadAuthItem();
        
        if(isset($_POST['AuthItem']))
        { 
            $auth = Yii::app()->authManager;
            $authItem  = $auth->getAuthItem($_POST['old_name']);
            $authItem->name = $_POST['AuthItem']['name'];
            //$authItem->type = $_POST['AuthItem']['type'];
            $authItem->description = $_POST['AuthItem']['description'];
            $authItem->bizrule = $_POST['AuthItem']['bizrule'];
            $authItem->data = $_POST['AuthItem']['data'];
            $auth->saveAuthItem($authItem,$_POST['old_name']);
            // Was name changed?
            if($_POST['old_name']<>$_POST['AuthItem']['name']) {
                $sql = sprintf("UPDATE AuthItemChild SET parent='%s' WHERE parent='%s'",$_POST['AuthItem']['name'],$_POST['old_name']);
                $command = Yii::app()->db->createCommand($sql);
                $command->execute();
                $sql = sprintf("UPDATE AuthItemChild SET child='%s' WHERE child='%s'",$_POST['AuthItem']['name'],$_POST['old_name']);
                $command = Yii::app()->db->createCommand($sql);
                $command->execute();
            }
            // Store parents
            if( count($_POST['parents'])>0 ) {
                foreach( $_POST['parents'] as $parent ) {
                    if( !$auth->hasItemChild($parent, $authItem->name) )
                        $auth->addItemChild($parent, $authItem->name);
                }
            }
            //$this->setFlash( 'update', $authItem );
            $this->redirect(array('admin','filter'=>'0,2'));
        }
        $parents = $this->getItemParents( $authItem->name );
        //var_dump( $parents );
        $this->render('update',array('authItem'=>$authItem,'itemParents'=>$parents));
    } // }}} 
    // {{{ actionDelete
    /**
     * Executes any command triggered on the admin page.
     */
    public function actionDelete()
    {
        $this->checkAccess('admin');
        if(Yii::app()->request->isPostRequest)
        {
            // we only allow deletion via POST request
            $auth = Yii::app()->authManager;
            $auth->removeAuthItem($_GET['id']);
            // Delete children
            $sql = sprintf("DELETE FROM AuthItemChild WHERE parent='%s' OR child='%s'",$_GET['id'],$_GET['id']);
            $command = Yii::app()->db->createCommand($sql);
            $command->execute();
            $this->redirect(array('admin'));
        }
        else
            throw new CHttpException(400,'Invalid request...');
    } // }}} 
    // {{{ ClearAll
    public function actionClearAll()
    {
        if(!Yii::app()->user->checkAccess('admin'))
            throw new CHttpException(500,Yii::t('site',"Sorry, you don't have enough privileges to perform this task."));

        Yii::app()->authManager->clearAll();
        $this->redirect(array('admin'));
    } // }}} 
    // }}} 
    // {{{ Other Methods
    // {{{ getChildren
    public function getChildren( $name, $level=1 )
    {
        $sql = "SELECT i.* FROM AuthItemChild ic LEFT JOIN AuthItem i ON ic.child=i.name WHERE ic.parent=:name";
        $command=Yii::app()->db->createCommand($sql);
        $command->bindParam(":name",$name,PDO::PARAM_STR);
        $children=$command->queryAll();
        if( count($children)>0 ) {
            foreach( $children as $n=>$child ) {
                $children[$n]['level'] = $level;
                $children[$n]['children'] = $this->getChildren($child['name'],$level+1);
            }
        }
        return $children;
    } // }}} 
    // {{{ loadAuthItem
    /**
     * Returns the data model based on the primary key given in the GET variable.
     * If the data model is not found, an HTTP exception will be raised.
     * @param integer the primary key value. Defaults to null, meaning using the 'id' GET variable
     */
    protected function loadAuthItem($name=null)
    {
        if($this->_authItem===null)
        {
            if($name!==null || isset($_GET['name']))
                $this->_authItem=AuthItem::model()->findbyPk($name!==null ? $name : $_GET['name']);
            if($this->_authItem===null || Yii::app()->user->isGuest)
                throw new CHttpException(500,'The requested Auth Item does not exist.');
        }
        return $this->_authItem;
    } // }}} 
    // {{{ getItemParents
    /**
     * gets an auth item's parents
     *
     * @param   string  $name   Item name
     */
    public function getItemParents( $name )
    {
        $sql = "SELECT parent FROM AuthItemChild WHERE child=:name GROUP BY parent ORDER BY parent";
        $command = Yii::app()->db->createCommand($sql);
        $command->bindParam(":name",$name,PDO::PARAM_STR);
        $rows=$command->queryAll();
        foreach( $rows as $row ) {
            $parents[] = $row['parent'];
        }
        return $parents;
    } // }}} 
    // }}} 
}
?>
